home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-05-18 | 11.8 KB | 390 lines | [TEXT/MPS ] |
- INCLUDE 'SysEqu.a' ;the usual system equates & macros
- INCLUDE 'Traps.a'
- INCLUDE 'QuickEqu.a'
-
- newPtrClear FUNC EXPORT
-
- IMPORT SAVERETA1
-
- MOVE.L (SP)+,A1
- MOVE.L (SP)+,D0
- _NewPtr clear
- MOVE.L A0,(SP)
- JMP SAVERETA1
-
- ENDF
-
-
- Rotate PROC EXPORT
- ;------------------------------------------------------------------------
- ;
- ; PROCEDURE Rotate (sourceMap, destMap : bitMap );
- ;
- ; given a source and destination bitmap rotate it CCW 90°…
- ; bitmap can be of any size, we will align on a word boundaries (v & h)
- ;
- ;-------------------------------------------------------------------------------
- ; a0 = result of _newPtr call | d0 = size of bitMap to allocate
- ; a1 = ptr to src bitMap | d1 = width/2 (source)
- ; a2 = ptr to dest bitMap | d2 = height/2 (source)
- ; a3 = dest bits | d3 = left | top
- ; a4 = copy of dest bits | d4 = ctrPt.h
- ; a5 = not used | d5 = ctrPt.v
- ; a6 = not used | d6 = right | bottom
- ; a7 = not used | d7 = rowBytes of dest bitMap
- ;-------------------------------------------------------------------------------
- ; ***********************************************************************
- ; * *
- ; * Initialize destination bitMap (destMap), etc… *
- ; * *
- ; ***********************************************************************
- ; parameter offsets
- ;
- DestMap EQU 4+4 ; offset to dest bitmap ^
- SourceMap EQU DestMap + 4 ; offset to source bitmap ^
- ;
- ; create local stack frame, and save some registers
- ; make room for dest rect to be passed back
- ;
- link a6,#0 ; set up a stack frame (no bytes)
- movem.l d3-d7/a2-a5,-(sp) ; save registers pascal may need
-
- move.l SourceMap(a6),a1 ; point to the source BitMap
- move.l DestMap(a6),a2 ; point to the dest BitMap
- ;
- ; compute height of source BitMap rounded up to nearest word
- ;
- move.w bounds+bottom(a1),d7; get bottom and put in d7
- sub.w bounds+top(a1),d7 ; bottom - top = height, put in d7
- move.w d7,d0 ; save a copy of height for later
- ; rnd = (height+15)/16, follows:
- addi.w #15,d7 ; add 15 to the height, put in d7
- lsr #4,d7 ; divide by 16
- lsl #1,d7 ; multiply by 2 = rowBytes of dest bitMap
- ;
- ; d7 now contains rowBytes of dest bitMap
- ;
- ; now compute the destRect for dest bitMap
- ;
- ; compute center point of Source rect
- ; note the center points are not necess. the
- ; same in the vert dir. relative to srcMap
- ; because of rounding that follows (i.e. height
- ; of srcMap is dir. prop. to RowBytes of destMap)
- lsr #1,d0 ; divide height by 2
- move.w d0,d2 ; make a copy of height/2 for later
- move.w bounds+top(a1),d5 ; get 'top' of source rect
- add.w d0,d5 ; d5 now contains vert component of ctr pt
- ; compute the width of src rect & put in d4
- move.w bounds+right(a1),d3 ; get right and put in d3
- sub.w bounds+left(a1),d3 ; right - left = width, put in d3
- lsr #1,d3 ; divide width by 2
- move.w d3,d1 ; make a copy of width/2 for later
- move.w bounds+right(a1),d4 ; get right of source rect
- sub.w d3,d4 ; d4 now contains horiz component of ctr pt
- ;
- ; now get center point and compute bounds for dest bitMap
- ; height and width are reversed now for the 2 bitMaps
- ;
- ; left :=ctrPt.h - height/2
- ; top :=ctrPt.v - width/2
- ; right :=ctrPt.h + height/2
- ; bottom:=ctrPt.v + width/2
- ; SetRect(rect, left, top, right, bottom) put data in direct to
- ; avoid the overhead of a trap call
- ;
- ; compute 'top'
- move.w d5,d3 ; get a copy of ctrPt.v and put in d3
- sub.w d1,d3 ; ctrPt.v - width/2 = 'top' in d3
- swap d3 ; move 'top' to hiword
- ; compute 'left'
- move.w d4,d3 ; get a copy of ctrPt.h and put in loword d3
- sub.w d2,d3 ; ctrPt.h - height/2 = 'left' in loword d3
- ;
- ; we now have 'top' in hiword & 'left' in loword d3
- ;
- ; compute 'bottom'
- move.w d5,d6 ; get a copy of ctrPt.v in of d3
- add.w d1,d6 ; ctrPt.v + width/2 = 'bottom' in d3
- swap d6 ; move 'bottom' to hiword
- ; compute 'right'
- move.w d4,d6 ; get a copy of ctrPt.h and put in loword d6
- add.w d2,d6 ; ctrPt.h + height/2 = 'right' in loword d6
- ;
- ; we now have 'bottom' in hiword & 'right' in loword d6
- ;
- ; assign data to dest bitMap structure directly
- ;
- move.w d7,rowBytes(a2) ; put in rowBytes direct for dest bitMap
- move.l d3,bounds+topLeft(a2) ; put the coord pair in direct
- move.l d6,bounds+botRight(a2) ; put the coord pair in direct
- move.w d7,d0 ; put rowbytes in d0
- mulu rowBytes(a1),d0 ; multiply rowBytes src*dest = d0
- lsl #3,d0 ; multiply d0 by 8 for size of dest bitMap
- _NewPtr clear ; allocate size of dest bitMap (a2 pts to it)
- move.l a0,baseaddr(a2) ; move contents of a0 to baseAddr field
- ; of dest bitMap structure
-
- ;-------------------------------------------------------------------------------
- ; a0 = baseAddr for our locals | d0 = rowbytes of srcMap
- ; a1 = points to bits of src bitMap | d1 = width/2 (source)
- ; a2 = ptr to dest bitMap | d2 = height/2 (source)
- ; a3 = dest bits | d3 = current word srcMap
- ; a4 = | d4 = copy of width of srcMap
- ; a5 = not used | d5 = current destMap word
- ; a6 = not used | d6 = insideLoop count (current bit)
- ; a7 = not used | d7 = rowBytes of dest bitMap
- ;-------------------------------------------------------------------------------
- ; ***********************************************************************
- ; * *
- ; * Start actual rotation of bitMaps *
- ; * *
- ; ***********************************************************************
- ; Assumptions:
- ; height of destination bitMap = rowBytes of srcMap
- ;
- ;
- ; Get the baseAddr for our locals into a0 - this will make our program much
- ; more readable as we will let the assembler do all the addr location calcs
- ; for us. The addresses will be a fixed number while the programs is
- ; (locked down) and running, therefore, there is no runtime penalty for
- ; doing this addr calculation
- ;
-
- lea localVars,a0
-
- ; Synchronize with the TickCount rollover.
- move.l ticks, d0 ; get the time
- @1 cmp.l ticks, d0 ; changed yet?
- beq.s @1 ; nope: loop
-
- ; Strobe the starting time.
- move.l ticks, startTime-localVars(a0) ; save starting time, in ticks
-
- ;
- ; initialize d0 to contain the pointer to the srcMap
- ;
- move.w rowbytes(a1),d0 ; get rowbytes of srcMap
-
- ;
- ; get regs pointing to bits
- ;
- move.l (a1),a1 ; a1 pts to BITS of src bitMap
- move.l (a2),a3 ; a3 pts to BITS of dest bitMap
-
- ;
- ; compute the lower left corner of the destMap - this maps to the upper left
- ; corner of the srcMap and will be used as base from which to offset into
- ; the dest map when we need to set a bit
- ;
- clr.l d1 ; clear d1
- move.w d0,d1 ; load rowBytes of srcMap
- ; (rowBytes of srcMap = ht of destMap)
- lsl.w #3,d1 ; multiply by 8 to get ht of destMap when rot'd
- mulu.w d7,d1 ; multiply by rowbytes(destMap) = #words in
- sub.w d7,d1 ; destMap less one row
- add.l a3,d1 ; add the computed offset to the baseAddr of destMap
- move.l d1,lowerLeft-localVars(a0) ; init lowerLeft
- ;
- ;-------------------------------------------------------------------------------
- ; a0 = baseAddr for our locals | d0 = rowbytes of srcMap
- ; a1 = points to bits of src bitMap | d1 = SCRATCH
- ; a2 = SCRATCH | d2 = colmCounter
- ; a3 = dest bits | d3 = current srcMap word
- ; a4 = SCRATCH | d4 = colmBitLoop counter
- ; a5 = not used | d5 = current word destMap
- ; a6 = not used | d6 = insideLoop count (current bit)
- ; a7 = not used | d7 = rowBytes of dest bitMap
- ;-------------------------------------------------------------------------------
- ;
-
- ; _Debugger;
-
- ; init wordCount to zero
- ;
- move.w #0,wordCount-localVars(a0) ; set wordCount to one before we start
- ;
- ; init colmLoop counter
- ;
- move.w d7,d2 ; get rowBytes(dest)
- lsr #1,d2 ; divide by 2 - d2 now contains the outer counter
- move.w d2,colmCount-localVars(a0) ; put the max value away for reference
- moveq.l #0,d2 ; set d2 to zero since we use it for the counter
-
- colmLoop
- ;
- ; this is the outside loop
- ;
- move.w #15,d4 ; init colmBitLoop counter to 15
- move.l lowerLeft-localVars(a0), a2 ; init currentWord
-
- colmBitLoop
- ;
- ; this is the loop that does the bit counting in the destMap - it is really a
- ; misuse of the 'dbra' instruction since it is not an independent loop but it
- ; is a quite cheap method of doing our counting
- ;
-
- cmp.w #7, d4 ; are we doing high byte or low?
- bgt dobyte1 ; skip if high byte
- addq #1, a2 ; else point to low byte
- dobyte1
-
- rowLoop
- ;
- ; loop across each row in the srcMap and keep count each time we do a row
- ; this 'rowCount' will used to compute the offset from 'lowerLeft'
- ;
- move.w (a1)+, d3 ; get a word to rotate into d3
- addq.w #2,wordCount-localVars(a0) ; add 1 for each word •••jdo•••
-
- add.w d3, d3 ; test next bit in the current source word
- bcc.s NoBitToChange ; if bit’s not set, skip to next
- bset d4, (a2) ; set proper bit in high or low byte in currentWord
- noBitToChange
- sub.l d7, a2 ; subtract rowBytes(destMap) from current word
-
- ; Do the same as above, fifteen more times.
- add.w d3, d3
- bcc.s @1
- bset d4, (a2)
- @1 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @2
- bset d4, (a2)
- @2 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @3
- bset d4, (a2)
- @3 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @4
- bset d4, (a2)
- @4 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @5
- bset d4, (a2)
- @5 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @6
- bset d4, (a2)
- @6 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @7
- bset d4, (a2)
- @7 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @8
- bset d4, (a2)
- @8 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @9
- bset d4, (a2)
- @9 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @10
- bset d4, (a2)
- @10 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @11
- bset d4, (a2)
- @11 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @12
- bset d4, (a2)
- @12 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @13
- bset d4, (a2)
- @13 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @14
- bset d4, (a2)
- @14 sub.l d7, a2
-
- add.w d3, d3
- bcc.s @15
- bset d4, (a2)
- @15 sub.l d7, a2
-
- ;
- ; at this point we've just completed a word from the srcMap
- ;
- cmp wordCount-localVars(a0),d0 ; cmp wordCount to rowBytes-are we done with a row ?
- bne rowLoop ; no - do another word
-
- cmp.w #7, d4 ; did we do high byte or low?
- bgt dobyte2 ; skip if high byte
- subq #1, a2 ; else undo the fudge to a2
- dobyte2
-
- ;
- ; we just completed a row so add 2 to the count
- ;
- move.w #0,wordCount-localVars(a0) ; •••jdo••• reset wordCount to zero
-
- ;
- ; the following use of dbra keeps track of our destMap bit for us
- ;
- move.l lowerLeft-localVars(a0), a2 ; re-init currentWord
- ; set the currentWord to the lowerLeft(current)
- ; lowerLeft is moved over (right) by a word each
- ; time we do a row in the srcMap
- dbra d4,colmBitLoop ; go thru the bits (15->0) in the
- ; destMap - then exit and do it
- ; again for rowBytes/2 times
-
- ;
- ; were done counting thru the bits of a destMap word - at this point we have
- ; actually finished a column in the destMap. The column is a multiple of
- ; 16 bits wide (and being at least 1 colm) and as tall as the destMap is
- ; (which is also equal to rowBytes of the srcMap)
- ;
- addq.l #2,lowerLeft-localVars(a0) ; this moves us into the next
- ; 'column' of bits in the destMap
- addq.w #1,d2 ; add 1 to the colmLoop counter
- cmp colmCount-localVars(a0),d2 ; are we done yet ?
- bne colmLoop ; no - do it again
- ; else we're done
- ;
- ; were done so lets do our clean-up/restore and go away gracefully
- ;
- move.l ticks, d0 ; get the current time…
- sub.l startTime-localVars(a0), d0 ; …less starting time
- _Debugger ; and let me see the time it took
-
- movem.l (sp)+,d3-d7/a2-a5 ; restore registers
- unlk a6 ; clean up stack frame
- move.l (sp)+,a0 ; return address
- add.l #8,sp ; pop parameters off stack
- jmp (a0) ; bye y'all!
-
- ;
- ; set up our data storage area
- ;
- localVars ; the beginning of our local var storage area
- colmCount ds.w 1
- currentWord ds.l 1
- lowerLeft ds.l 1
- wordCount ds.w 1
- startTime ds.l 1
-
- ENDP
-
- END
-
-
-